package alocador.entidades;

import java.util.Iterator;

import alocador.exceptions.DataInvalidaException;
import alocador.exceptions.EventoInvalidoException;
import alocador.util.VerificaInvalido;

/**
 * O pacote entidades diz respeito as entidades do Sistema, ou seja, Evento e Horario
 * Classe que modela a Entidade Evento. Realiza todas operacoes relacionadas a ele
 */

public abstract class Evento {

	private String id;
	private String nome;
	private String area;
	private String contato;
	private int repeticoes;
	private String inicio;
	private String fim;
	
	//construtor
	public Evento(String id, String nome, String inicio,
			String fim, String area, String contato, int repeticoes)
			throws EventoInvalidoException, DataInvalidaException {
		
		verificaExcecoes(id, nome, area, contato, repeticoes);
		this.id = id;
		this.nome = nome;
		this.area = area;
		this.contato = contato;
		this.inicio = inicio;
		this.fim = fim;
		this.repeticoes = repeticoes;
	}
	
	/**
	 * Retorna Data de Inicio do Evento
	 * @return 
	 * 		Data de Inicio do Evento
	 */
	public String getInicio() {
		return this.inicio;
	}

	/**
	 * Retorna Data do Fim do Evento
	 * @return 
	 * 		Data do Fim do Evento
	 */
	public String getFim() {
		return this.fim;
	}

	/**
	 * Retorna o Identificador do Evento
	 * @return 
	 * 		Identificador do Evento
	 */
	public String getId() {
		return this.id;
	}

	/**
	 * Retorna o Nome do Evento
	 * @return 
	 * 		Nome do Evento
	 */
	public String getNome() {
		return this.nome;
	}

	/**
	 * Retorna a lista contendo todos horarios de um evento
	 * @return 
	 * 		Lista de Horario ou um Horario de um evento
	 */
	protected abstract Object getHorariosDoEvento();
	
	/**
	 * Itera sobre o(s) horario(s) de um Evento
	 * @return
	 * 		Iterator de um Horario
	 */
	public abstract Iterator<Horario> horarioIterator();
	
	/**
	 * Retorna Area de Interesse do Evento
	 * @return 
	 * 		Area de Interesse do Evento
	 */
	public String getArea() {
		return this.area;
	}

	/**
	 * Retorna o Reponsavel pelo Evento
	 * @return 
	 * 		Responsavel pelo Evento
	 */
	public String getContato() {
		return this.contato;
	}

	/**
	 * Retorna o numero de Repeticoes do Evento
	 * @return 
	 * 		Numero de Repeticoes do Evento
	 */
	public int getRepeticoes() {
		return this.repeticoes;
	}

	/**
	 * Modifica o numero de Repeticoes do Evento
	 * @param novaRepeticao
	 *      Quantidade de Repeticoes do Evento
	 */
	protected void setRepeticoes(int novaRepeticao) {
		this.repeticoes = novaRepeticao;
	}
	
	/**
	 * Retorna Quantidade de Horarios de um Evento
	 * @return
	 * 		Quantidade de Horarios de um Evento
	 */
	public abstract int numDeHorarios();

	/**
	 * Verifica se Evento contem determinado Horario
	 * @param data
	 *      Data a ser verificada
	 * @return 
	 * 		True, caso Evento contenha horario. False, caso contrario
	 * @throws DataInvalidaException
	 * 		Caso a data esteja em formato errado, 30/02, por exemplo
	 */
	protected abstract boolean contemHorario(String data) throws DataInvalidaException;

	/**
	 * Retorna todos Eventos no mesmo Local e Data
	 * @return 
	 * 		Eventos no mesmo Local e Data
	 */
	public final boolean temConflitoCom(Evento evento, Evento outroEvento) {
		Iterator<Horario> it = evento.horarioIterator();
		Iterator<Horario> itOutro = outroEvento.horarioIterator();
		
		while (it.hasNext()){
			Horario h = it.next();
			while(itOutro.hasNext()){
				if(h.temChoqueHorario(itOutro.next())  ){
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Verifica igualdade entre dois Eventos
	 * @return
	 * 		True, se os objetos forem iguais. False, caso contrario
	 */
	@Override
	public boolean equals(Object obj) {
		if ((obj == null) || !(obj instanceof Evento))
			return false;

		Evento other = (Evento) obj;
		return (getId().equals(other.getId()));
	}
	
	/**
	 * Retorna as informacoes de um Evento
	 * @return
	 * 	Informacoes de um Evento
	 */
	public abstract String toString();

	/**
	 * Verifica Excecoes dos Atributos de Evento
	 */
	protected void verificaExcecoes(String id, String nome, String area,
			String contato, int repeticoes) throws EventoInvalidoException {

		if (VerificaInvalido.basico(id))
			throw new EventoInvalidoException("Identificacao Invalida");

		if (VerificaInvalido.basico(nome))
			throw new EventoInvalidoException("Atributo invalido.");

		if (VerificaInvalido.basico(area))
			throw new EventoInvalidoException("Atributo invalido.");

		if (VerificaInvalido.basico(contato))
			throw new EventoInvalidoException("Atributo invalido.");

		if (repeticoes < 0)
			throw new EventoInvalidoException("Atributo invalido.");

	}
}